Hexagonal Grid Traversal
https://gyazo.com/d17fc59f4074808cabddfe0bea211198
六角形タイルのトラバーサル
やり方
https://gyazo.com/e1bc60a6d63415ea6a51105d49ab7530
code:glsl
vec3 traverseHex( vec2 ro, vec2 rd ) {
vec2 hex = findNearestHex( ro + rd * 1E-2 * SIZE );
vec2 normal = vec2( 0.0 );
float dist = 1E9;
for ( int i = 0; i < 3; i ++ ) {
vec2 dir = cis( PI * ( float( i ) + 0.5 ) / 3.0 );
float rdd = dot( rd, dir );
float src = -dot( ro - hex, dir ) / rdd;
float dst = abs( SQRT3 / 2.0 * SIZE / rdd );
float dist2 = src + dst;
if ( dist2 < dist ) {
dist = dist2;
normal = -dir * sign( rdd );
}
}
return vec3( normal, dist );
}
セル探しをHexagonal Gridに置き換える
面は、 rd を踏まえて3枚との衝突判定を行い、一番短いものを採用する
60度ずつぐるぐるする dir が面の向きを表す
rdd が正であればその方向の面との衝突判定をするし、負であれば逆の方向の面との衝突判定をする
dst で SIZE に SQRT3 / 2.0 を乗じている
これは中心から辺までの距離が$ \frac{\sqrt3}{2}単位のため
($ 1なのは中心から頂点までの距離)
これ忘れやすそうなので注意
mat3を用いた最適化
code:glsl
vec3 traverseHex( vec2 ro, vec2 rd ) {
vec2 hex = findNearestHex( ro + rd * 1E-2 * SIZE );
mat3 dir = mat3(
vec3( SQRT3 / 2.0, 0.5, 0.0 ),
vec3( 0.0, 1.0, 0.0 ),
vec3( -SQRT3 / 2.0, 0.5, 0.0 )
);
vec3 rdd = vec3( rd, 0.0 ) * dir;
vec3 src = -( vec3( ro - hex, 0.0 ) * dir ) / rdd;
vec3 dst = abs( SQRT3 / 2.0 * SIZE / rdd );
vec3 distv = src + dst;
float dist = min( min( distv.x, distv.y ), distv.z );
vec3 mask = step( distv, vec3( dist ) );
vec2 normal = -( dir * mask ).xy * sign( dot( rdd, mask ) );
return vec3( normal, dist );
}